package com.huwaiwai001.aqs;

import java.io.Serializable;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class TwinsLock implements Serializable {

    private static final long serialVersionUID = 4109184969368402369L;

    private Sync sync = new Sync(2);

    public void lock() {
        sync.acquireShared(1);
    }

    public boolean tryLock() {
        return sync.tryAcquireShared(1) >= 0;
    }

    public void unlock() {
        sync.releaseShared(1);
    }

    private static final class Sync extends AbstractQueuedSynchronizer implements Serializable {

        private static final long serialVersionUID = -1888548868693702643L;

        Sync(int initCount) {
            if (initCount <= 0) {
                throw new IllegalArgumentException("资源数必须大于0");
            }
            setState(initCount);
        }

        @Override
        protected int tryAcquireShared(int arg) {
            if (arg <= 0) {
                throw new IllegalArgumentException("申请资源数必须大于0");
            }

            int state = getState();
            int newState = state - arg;

            if (newState < 0 || compareAndSetState(state, newState)) {
                return newState;
            }
            return -1;
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            if (arg <= 0) {
                throw new IllegalArgumentException("释放资源数必须大于0");
            }
            for (;;) {
                int state = getState();
                int newState = state + arg;
                if (compareAndSetState(state, newState)) {
                    return true;
                } else {
                    System.out.println(Thread.currentThread().getName() + " unlock fail");
                }
            }
        }

    }
}
